// ==UserScript==
// @name         Ecommerce Helper
// @namespace    http://tampermonkey.net/
// @version      1.3.0
// @description  download product image
// @author       birdpeace
// @match        https://detail.1688.com/offer/*
// @match        https://my.xiapibuy.com/*
// @match        https://*.shopeex.cn/*
// @match        https://seller.my.shopee.cn/*
// @require      http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js
// @grant        MIT
// ==/UserScript==
    
(function () {
  'use strict';

  class CommonHelper {
      static log(...message) {
          console.log('[Ecommerce Helper]', ...message);
      }
      static downloadFile(content, filename, contentType = 'text/html') {
          // 创建a链接
          let eleLink = document.createElement('a');
          eleLink.download = filename;
          eleLink.style.display = 'none';
          // 字符内容转变成BlobURL
          let blob = new Blob([content], { type: contentType });
          eleLink.href = URL.createObjectURL(blob);
          // 触发点击(开始下载)
          document.body.appendChild(eleLink);
          eleLink.click();
          // 移除标签
          setTimeout(function () {
              document.body.removeChild(eleLink);
          }, 1000);
      }
      static async saveFile(fileName, content, parentHandle) {
          if (!parentHandle) {
              parentHandle = await window.showDirectoryPicker();
              if (!(await CommonHelper.verifyPermission(parentHandle))) {
                  return;
              }
          }
          let newFileHandle = await parentHandle.getFileHandle(fileName, {
              create: true,
          });
          // Create a FileSystemWritableFileStream to write to.
          const writable = await newFileHandle.createWritable();
          await writable.write(content);
          await writable.close();
      }
      static async saveFileFromUrl(fileName, url, parentHandle) {
          if (!parentHandle) {
              parentHandle = await window.showDirectoryPicker();
              if (!(await CommonHelper.verifyPermission(parentHandle))) {
                  return;
              }
          }
          let newFileHandle = await parentHandle.getFileHandle(fileName, {
              create: true,
          });
          // Create a FileSystemWritableFileStream to write to.
          const writable = await newFileHandle.createWritable();
          // Make an HTTP request for the contents.
          const response = await fetch(url);
          // Stream the response into the file.
          if (response.body) {
              return (await response.body) && response.body.pipeTo(writable);
          }
          // pipeTo() closes the destination pipe by default, no need to close it.
      }
      static async verifyPermission(fileHandle) {
          const options = {
              mode: 'readwrite',
          };
          // Check if permission was already granted. If so, return true.
          if ((await fileHandle.queryPermission(options)) === 'granted') {
              return true;
          }
          // Request permission. If the user grants permission, return true.
          if ((await fileHandle.requestPermission(options)) === 'granted') {
              return true;
          }
          // The user didn't grant permission, so return false.
          return false;
      }
      static toQueryString(params, prefix = '?') {
          let result = '';
          for (let key in params) {
              result += `&${key}=${params[key]}`;
          }
          if (result.length > 0) {
              return (prefix ? '?' : '') + result.slice(1);
          }
          return result;
      }
  }

  class PlatformBaseManager {
      constructor() {
          this.viewContainer = jQuery('<div class="ecommercy-container"></div>').css({
              position: 'fixed',
              'z-index': 10000,
          });
          this.viewContainer.prependTo(document.body);
      }
      init() { }
      async saveProductInfo(productInfo) {
          let parentHandle = await window.showDirectoryPicker();
          if (!(await CommonHelper.verifyPermission(parentHandle))) {
              return;
          }
          let dirHandle = await parentHandle.getDirectoryHandle(productInfo.title, {
              create: true,
          });
          CommonHelper.saveFile('index.html', this.renderProductContent(productInfo), dirHandle);
          productInfo.imgList.map(({ fileName, imgUrl }) => {
              CommonHelper.saveFileFromUrl(fileName, imgUrl, dirHandle);
          });
          productInfo.tierList.map((tier) => {
              tier.options.map(({ fileName, imgUrl }) => {
                  CommonHelper.saveFileFromUrl(fileName, imgUrl, dirHandle);
              });
          });
      }
      renderProductContent(productInfo) {
          let pageContent = `
  <title>${productInfo.title}</title>
  <div style="max-width:1180px;margin:0 auto">
  <h2><a href="${productInfo.href}">${productInfo.title}</a></h2>
  <h3>商品图片</h3>
  <div>
  ${productInfo.imgList
            .map((img) => `<img style="width: 100px" src="${img.fileName}">`)
            .join('')}
  </div>
  ${productInfo.tierList
            .map((tier) => {
            let tierContent = tier.options
                .map((option) => `
  <div style="display:inline-block;margin-right:10px">
     <p>${option.title}</p>
     <img style="width: 100px" src="${option.fileName}" download="${option.fileName}">
  </div>
  `)
                .join('');
            return `
  <h4>${tier.title}</h4>
  <div>${tierContent}</div>
  </div>
  `;
        })
            .join('')}
  `;
          return pageContent;
      }
      saveOrderList(orderList) {
          let bodyTemplate = orderList
              .map((order) => `
    <tr>
        <td data-desc="订单编号">${order.orderSn}</td>
        <td data-desc="运单编号">${order.trackingNo}</td>
        <td data-desc="收件人">${order.buyerName}</td>
        <td data-desc="收货地邮编">${order.addressZipcode}</td>
        <td data-desc="收件人电话">${order.buyerPhone}</td>
        <td data-desc="收件省份">${order.addressState}</td>
        <td data-desc="收件城市">${order.addressCity}</td>
        <td data-desc="收件地区">${order.addressDistrice}</td>
        <td data-desc="收件详细地址">${order.buyerAddress}</td>
        <td data-desc="重量KG"></td>
        <td data-desc="体积"></td>
        <td data-desc="代收货款"></td>
        <td data-desc="货物类型">普货</td>
        <td data-desc="备注"></td>
        <td data-desc="中文品名">玩具</td>
        <td data-desc="英文品名">toys</td>
        <td data-desc="件数">${order.amount}</td>
        <td data-desc="申报价值">${order.totalPrice}</td>
        <td data-desc="申报价值币别">${order.currency}</td>
        <td data-desc="物品分类1"></td>
        <td data-desc="物品分类2"></td>
        <td data-desc="物品分类3"></td>
        <td data-desc="商品备注"></td>
        <td data-desc="购买类型"></td>
        <td data-desc="URL">${order.productUrl}</td>
        <td data-desc="出口商品类型"></td>
        <td data-desc="商品规格"></td>
    </tr>
            `)
              .join('');
          let resultContent = `<table>
    <thead>
          <tr>
          <th>订单编号</th>
          <th>运单编号</th>
          <th>收件人</th>
          <th>收货地邮编</th>
          <th>收件人电话</th>
          <th>收件省份</th>
          <th>收件城市</th>
          <th>收件地区</th>
          <th>收件详细地址</th>
          <th>重量KG</th>
          <th>体积</th>
          <th>代收货款</th>
          <th>货物类型</th>
          <th>备注</th>
          <th>中文品名</th>
          <th>英文品名</th>
          <th>件数</th>
          <th>申报价值</th>
          <th>申报价值币别</th>
          <th>物品分类1</th>
          <th>物品分类2</th>
          <th>物品分类3</th>
          <th>商品备注</th>
          <th>购买类型</th>
          <th>URL</th>
          <th>出口商品类型</th>
          <th>商品规格</th>
          </tr>
    </thead>
    <tbody>${bodyTemplate}</tbody>
</table>
`;
          let dateString = new Date().toLocaleDateString().replace(/\//g, '_');
          CommonHelper.saveFile(`order-list_${dateString}.xls`, resultContent
          //   'application/vnd.ms-excel'
          );
      }
  }

  class AlibabaManager extends PlatformBaseManager {
      init() {
          this.getProductInfo()
              .then((productInfo) => {
              CommonHelper.log('product detected', productInfo);
              let button = jQuery('<button class="btn btn-primary">下载图片展示页</button>');
              button.prependTo(document.body);
              button.on('click', () => {
                  this.saveProductInfo(productInfo);
                  //downloadFile(renderProductContent(productInfo), productInfo.title + '.html')
              });
          })
              .catch((err) => { });
      }
      getProductInfo() {
          let videoList = $('video.lib-video')
              .map((_, video) => {
              return {
                  src: video.src,
                  poster: video.poster,
                  duration: video.duration,
              };
          })
              .get();
          let tierList = $('.obj-sku')
              .map((_, item) => {
              return {
                  title: $(item).find('.obj-title').text(),
                  options: $(item)
                      .find('.image')
                      .map((_, item) => {
                      let title = $(item).attr('title') || '';
                      let imgUrl = $(item).data().imgs.original;
                      let suffix = imgUrl.split('.').pop();
                      return {
                          title: title,
                          imgUrl: imgUrl,
                          fileName: title + '.' + suffix,
                      };
                  })
                      .get(),
              };
          })
              .get();
          let imgList = $('.tab-trigger[data-imgs]')
              .map((index, item) => ({
              imgUrl: $(item).data().imgs.original,
              title: 'main_' + index,
              fileName: 'main_' + index + '.jpg',
          }))
              .get()
              .filter((img) => {
              return !tierList.some((tier) => {
                  return tier.options.some((option) => option.imgUrl === img.imgUrl);
              });
          });
          let result = {
              title: 'ali_' + $('#mod-detail-title > h1').text(),
              href: location.href,
              videoList: videoList,
              imgList,
              tierList,
          };
          return Promise.resolve(result);
      }
  }

  class ShopeeManager extends PlatformBaseManager {
      init() {
          this.getProductInfo()
              .then((productInfo) => {
              CommonHelper.log('product detected', productInfo);
              jQuery('<button class="btn btn-primary">下载图片展示页</button>')
                  .on('click', () => {
                  this.saveProductInfo(productInfo);
                  //downloadFile(renderProductContent(productInfo), productInfo.title + '.html')
              })
                  .appendTo(this.viewContainer);
          })
              .catch(() => { });
      }
      getProductInfo() {
          let paramList = [];
          if (location.pathname.startsWith('/product/')) {
              paramList = location.pathname.slice('/product/'.length).split('/');
          }
          else {
              paramList = location.pathname.split('.').slice(-2);
          }
          let [shopId, itemId] = paramList;
          if (!shopId || !itemId) {
              return Promise.reject();
          }
          return fetch(`https://my.xiapibuy.com/api/v2/item/get?itemid=${itemId}&shopid=${shopId}`)
              .then((resp) => resp.json())
              .then((data) => data.item)
              .then((productInfo) => {
              let tierList = productInfo.tier_variations.map((vari) => {
                  return {
                      title: vari.name,
                      options: vari.options.map((title, opIdx) => {
                          return {
                              title: title,
                              imgUrl: `https://cf.shopee.com.my/file/${vari.images[opIdx]}`,
                              fileName: title + '.jpg',
                          };
                      }),
                  };
              });
              let imgList = productInfo.images
                  .map((imgId, index) => ({
                  imgUrl: `https://cf.shopee.com.my/file/${imgId}`,
                  title: 'main_' + index,
                  fileName: 'main_' + index + '.jpg',
              }))
                  .filter((img) => {
                  return !tierList.some((tier) => {
                      return tier.options.some((option) => option.imgUrl === img.imgUrl);
                  });
              });
              return {
                  title: 'shopee_' + productInfo.name,
                  href: location.href,
                  //videoList: (productInfo.video_info_list || []).map(video => ({
                  //  src: video.
                  //})),
                  imgList,
                  tierList,
              };
          });
      }
  }

  class ShopeeOrderManager extends PlatformBaseManager {
      init() {
          let exportContainer = $(`
    <div class="export-container">
        <input type="number" value='3'  />
    </div>`);
          exportContainer.appendTo(this.viewContainer);
          jQuery('<button class="btn btn-primary">导出订单</button>')
              .on('click', () => {
              let pageSize = exportContainer.find('input').prop('value');
              this.getOrderList(pageSize).then((orderList) => {
                  if (orderList.length) {
                      this.saveOrderList(orderList);
                  }
              });
          })
              .appendTo(exportContainer);
      }
      getOrderList(pageSize = 40, pageNumber = 1) {
          let queryString = CommonHelper.toQueryString({
              SPC_CDS: '8655ecc6-a001-4356-bab2-f518bc4fd592',
              SPC_CDS_VER: 2,
              page_size: pageSize,
              page_number: pageNumber,
              total: 0,
              sort_by: 'confirmed_date_desc',
          });
          return fetch('https://seller.my.shopee.cn/api/v3/order/get_forder_list' + queryString)
              .then((resp) => resp.json())
              .then((resp) => resp.data.forders)
              .then((forderList) => {
              return Promise.all(forderList.map((forder) => {
                  let orderQueryString = CommonHelper.toQueryString({
                      SPC_CDS: '8655ecc6-a001-4356-bab2-f518bc4fd592',
                      SPC_CDS_VER: 2,
                      order_id: forder.order_id,
                  });
                  return fetch('https://seller.my.shopee.cn/api/v3/order/get_one_order' +
                      orderQueryString)
                      .then((resp) => resp.json())
                      .then((resp) => {
                      let order = resp.data;
                      let [addressState, addressZipcode, addressCity,] = order.shipping_address.split(', ').reverse();
                      // if (rest.length === 0) {
                      //   addressDistrice = ''
                      // }
                      return {
                          orderSn: forder.order_sn,
                          trackingNo: forder.third_party_tn,
                          buyerName: order.buyer_address_name,
                          buyerAddress: order.shipping_address,
                          buyerPhone: order.buyer_address_phone,
                          addressState,
                          addressCity,
                          addressDistrice: '',
                          addressZipcode,
                          amount: order.order_items.reduce((result, item) => result + item.amount, 0),
                          totalPrice: order.total_price,
                          currency: order.currency === 'MYR' ? 'RM' : order.currency,
                          productUrl: `https://shopee.com.my/product/${order.shop_id}/${order.order_items[0].item_id}`,
                      };
                  });
              }));
          });
      }
  }

  class ShopeexManager {
      init() {
          let panel = jQuery(`<div id="shopeex-toolkit">
  <button class="btn btn-primary">导出订单excel</button>
  <input type="number" value='50'  />
</div>`);
          panel
              .css({
              position: 'fixed',
              'z-index': 1,
          })
              .prependTo(document.body);
          let button = panel.find('button');
          button.on('click', () => {
              let pageSize = $('#shopeex-toolkit > input').prop('value');
              this.downloadOrderList(parseInt(pageSize || 50, 10));
          });
      }
      downloadOrderList(pageSize = 50) {
          fetch(location.origin + '/api/order/unPackage/list', {
              method: 'post',
              headers: {
                  token: localStorage.token,
                  'Content-Type': 'application/json;charset=UTF-8',
                  Accept: 'application/json, text/plain, */*',
              },
              credentials: 'same-origin',
              body: JSON.stringify({
                  orderSn: '',
                  shopId: 0,
                  shopeeStatus: 'READY_TO_SHIP',
                  trackingNumber: '',
                  userId: 0,
                  orderBy: 4,
                  pageNumber: 1,
                  pageSize,
              }),
          })
              .then((resp) => resp.json())
              .then((resp) => resp.data.list)
              .then((resp) => resp
              .map((order) => {
              return `
  <tr>
      <td data-desc="订单编号">${order.ordersn}</td>
      <td data-desc="运单编号">${order.trackingNo}</td>
      <td data-desc="收件人">${order.name}</td>
      <td data-desc="收货地邮编">${order.zipcode}</td>
      <td data-desc="收件人电话">${order.phone}</td>
      <td data-desc="收件省份">${order.state}</td>
      <td data-desc="收件城市">${order.city}</td>
      <td data-desc="收件地区">${order.district}</td>
      <td data-desc="收件详细地址">${order.fullAddress}</td>
      <td data-desc="重量KG"></td>
      <td data-desc="体积"></td>
      <td data-desc="代收货款"></td>
      <td data-desc="货物类型">普货</td>
      <td data-desc="备注"></td>
      <td data-desc="中文品名">玩具</td>
      <td data-desc="英文品名">toys</td>
      <td data-desc="件数">${order.orderItems.reduce((result, item) => result + item.variationQuantityPurchased, 0)}</td>
      <td data-desc="申报价值">${order.totalAmount}</td>
      <td data-desc="申报价值币别">${order.currency === 'MYR' ? 'RM' : order.currency}</td>
      <td data-desc="物品分类1"></td>
      <td data-desc="物品分类2"></td>
      <td data-desc="物品分类3"></td>
      <td data-desc="商品备注"></td>
      <td data-desc="购买类型"></td>
      <td data-desc="URL">https://shopee.com.my/product/${order.shopid}/${order.orderItems[0].itemId}</td>
      <td data-desc="出口商品类型"></td>
      <td data-desc="商品规格"></td>
  </tr>
          `;
          })
              .join(''))
              .then((orderListTemplate) => `<table>
      <thead>
            <tr>
            <th>订单编号</th>
            <th>运单编号</th>
            <th>收件人</th>
            <th>收货地邮编</th>
            <th>收件人电话</th>
            <th>收件省份</th>
            <th>收件城市</th>
            <th>收件地区</th>
            <th>收件详细地址</th>
            <th>重量KG</th>
            <th>体积</th>
            <th>代收货款</th>
            <th>货物类型</th>
            <th>备注</th>
            <th>中文品名</th>
            <th>英文品名</th>
            <th>件数</th>
            <th>申报价值</th>
            <th>申报价值币别</th>
            <th>物品分类1</th>
            <th>物品分类2</th>
            <th>物品分类3</th>
            <th>商品备注</th>
            <th>购买类型</th>
            <th>URL</th>
            <th>出口商品类型</th>
            <th>商品规格</th>
            </tr>
      </thead>
      <tbody>${orderListTemplate}</tbody>
  </table>
  `)
              .then((content) => {
              console.log(content);
              let dateString = new Date().toLocaleDateString().replace(/\//g, '_');
              CommonHelper.saveFile(`order-list_${dateString}.xls`, content
              //   'application/vnd.ms-excel'
              );
          });
          //downloadFile(renderProductContent(productInfo), productInfo.title + '.html')
      }
  }

  CommonHelper.log('start work!!');
  switch (location.hostname) {
      case 'detail.1688.com':
          new AlibabaManager().init();
          break;
      case 'my.xiapibuy.com':
          new ShopeeManager().init();
          break;
      case 'seller.my.shopee.cn':
          new ShopeeOrderManager().init();
          break;
      default:
          if (location.hostname.endsWith('.shopeex.cn')) {
              new ShopeexManager().init();
          }
  }

}());
